package com.abhinav;

public class Deadlock implements Runnable {
	First a = new First();
	Second b = new Second();

	Deadlock() {
		Thread.currentThread().setName("MainThread");
		Thread t = new Thread(this, "RacingThread");
		t.start();
		a.foo(b); // get lock on a in this thread.
		System.out.println("Back in main thread");
	}

	public void run() {
		b.bar(a); // get lock on b in other thread.
		System.out.println("Back in other thread");
	}

	public static void main(String args[]) {
		new Deadlock();
	}

}

class First {
	synchronized void foo(Second b) {
		String name = Thread.currentThread().getName();
		System.out.println(name + " entered First.foo()");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			System.out.println("First Interrupted");
		}
		System.out.println("Trying to call Second.last()");
		b.last();
	}

	synchronized void last() {
		System.out.println("Inside First.last");
	}
}

class Second {
	synchronized void bar(First a) {
		String name = Thread.currentThread().getName();
		System.out.println(name + " entered Second.bar");
		try {
			Thread.sleep(1000);
		} catch (Exception e) {
			System.out.println("Second Interrupted");
		}
		System.out.println(name + " trying to call First.last()");
		a.last();
	}

	synchronized void last() {
		System.out.println("Inside Second.last");
	}
}